﻿using System.Globalization;
using System.Linq;
using Microsoft.Practices.ServiceLocation;

namespace Eswat
{
	/// <summary>
	/// Default test services accessor.
	/// </summary>
	public class DefaultTestServiceAccessor : TestServiceAccessorBase
	{
		/// <summary>
		/// Singleton instance of the default test services accessor.
		/// </summary>
		public static DefaultTestServiceAccessor Instance = new DefaultTestServiceAccessor();

		/// <summary>
		/// Gets the service matching the specified key.
		/// </summary>
		/// <param name="key">The key.</param>
		/// <returns></returns>
		public dynamic Get(string key)
		{
			var svc = GetService<ITestService>(key);

			return (dynamic)svc;
		}

		/// <summary>
		/// Gets the service using the specified <paramref name="key"/>.
		/// </summary>
		/// <typeparam name="T">The type of service to obtain.</typeparam>
		/// <param name="key">The key.</param>
		/// <returns></returns>
		protected override T GetService<T>(string key)
		{
			ITestService service = null;

			// check if no ServiceLocator exists and return (skip all the try-catch blocks below)
			if (ServiceLocatorHelpers.IsNull()) return (T)service;

			// really? some locator frameworks throw exceptions... really?
			try { service = ServiceLocator.Current.GetInstance<ITestService>(key); }
			catch { }

			// verify name
			if (service != null && service.Name != key) service = null;

			if (service == null)
			{
				// really? some locator frameworks throw exceptions... really?
				try
				{
					// look at all registered services
					var services = ServiceLocator.Current.GetAllInstances<ITestService>();

					// no services found
					if (services.Count() > 0)
					{
						// search for it by name
						service = services.FirstOrDefault(svc => string.Compare(svc.Name, key, CultureInfo.InvariantCulture, CompareOptions.IgnoreCase) == 0);
					}
				}
				catch { }

				if (service == null)
				{
					// really? some locator frameworks throw exceptions... really?
					try
					{
						// could still be a single registration (example: Unity will not return multiple instances with a single, un-named registration)
						service = ServiceLocator.Current.GetInstance<ITestService>();

						// verify name
						if (service != null && string.Compare(service.Name, key, CultureInfo.InvariantCulture, CompareOptions.IgnoreCase) != 0) service = null;
					}
					catch { }
				}
			}

			return (T)service;
		}
	}
}
